package com.aliyun.heiyu.common.factory;

import com.aliyun.heiyu.common.entity.Constant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;

public class PropertiesFactory {
    private static final Logger logger = LoggerFactory.getLogger(PropertiesFactory.class);

    private static volatile Map<String,Properties> propertiesMap = new HashMap<>();

    public static Properties getProperties(String name) {
        synchronized (PropertiesFactory.class) {
            if (propertiesMap.get(name) == null) {
                Properties properties = createProperties(name);
                propertiesMap.put(name, properties);
            }
            return propertiesMap.get(name);
        }
    }

    private static Properties createProperties(String name){
        //create the properties file if necessary
        String propPath = Constant.DB_PATH() + name;

       HashMap<String, String> map = new HashMap<String, String>();
        map.put("a", "a");
        map.put("b", "b");
        map.put("c", "c");
        map.put("d", "d");
        map.put("e", "e");
        map.put("f", "f");
        map.put("g", "g");
        map.put("h", "h");
        map.put("i", "i");
        map.put("j", "j");
        map.put("k", "k");
        map.put("l", "l");
        map.put("m", "m");
        map.put("n", "n");
        map.put("o", "o");
        map.put("p", "p");
        map.put("q", "q");
        map.put("r", "r");
        map.put("s", "s");
        map.put("t", "t");
        map.put("u", "u");
        map.put("v", "v");
        map.put("w", "w");
        map.put("x", "x");
        map.put("y", "y");
        map.put("z", "z");

        map.put("A", "A");
        map.put("B", "B");
        map.put("C", "C");
        map.put("D", "D");
        map.put("E", "E");
        map.put("F", "F");
        map.put("G", "G");
        map.put("H", "H");
        map.put("I", "I");
        map.put("J", "J");
        map.put("K", "K");
        map.put("L", "L");
        map.put("M", "M");
        map.put("N", "N");
        map.put("O", "O");
        map.put("P", "P");
        map.put("Q", "Q");
        map.put("R", "R");
        map.put("S", "S");
        map.put("T", "T");
        map.put("U", "U");
        map.put("V", "V");
        map.put("W", "W");
        map.put("X", "X");
        map.put("Y", "Y");
        map.put("Z", "Z");

        map.put(":", ":");
        map.put("/", "/");
        map.put(File.separator, File.separator);
        map.put("1", "1");
        map.put("2", "2");
        map.put("3", "3");
        map.put("4", "4");
        map.put("5", "5");
        map.put("6", "6");
        map.put("7", "7");
        map.put("8", "8");
        map.put("9", "9");
        map.put("0", "0");
        map.put("_", "_");
        map.put("-", "-");
        map.put(".", ".");

        String temp = "";
        for (int i = 0; i < propPath.length(); i++) {
            if (map.get(propPath.charAt(i)+"")!=null) {
                temp += map.get(propPath.charAt(i)+"");
            }
        }
        propPath = temp;
        //logger.info("propPath ================== " + propPath);
        File file = new File(propPath);
        File parentFile = file.getParentFile();
        if(!parentFile.exists()){
            parentFile.mkdirs();
        }
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        //load properties: /user.name/db/*.properties has the high priority，classpath/*.propreties has the low priority
        Properties prop = new Properties();
        InputStream ins = null;
        try {
            ins = new BufferedInputStream(new FileInputStream(file));
            prop.load(ins);//加载属性列表
            if(prop == null || prop.isEmpty()){
                ins = PropertiesFactory.class.getClassLoader().getResourceAsStream(name);
                prop.load(ins);//加载属性列表
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }finally {
            if(ins != null){
                safeClose(ins);
            }
        }
        return prop;
    }

    public static void updateProperties(String name,Properties props){
        String propPath = Constant.DB_PATH() + name;

        HashMap<String, String> map = new HashMap<String, String>();
        map.put("a", "a");
        map.put("b", "b");
        map.put("c", "c");
        map.put("d", "d");
        map.put("e", "e");
        map.put("f", "f");
        map.put("g", "g");
        map.put("h", "h");
        map.put("i", "i");
        map.put("j", "j");
        map.put("k", "k");
        map.put("l", "l");
        map.put("m", "m");
        map.put("n", "n");
        map.put("o", "o");
        map.put("p", "p");
        map.put("q", "q");
        map.put("r", "r");
        map.put("s", "s");
        map.put("t", "t");
        map.put("u", "u");
        map.put("v", "v");
        map.put("w", "w");
        map.put("x", "x");
        map.put("y", "y");
        map.put("z", "z");

        map.put("A", "A");
        map.put("B", "B");
        map.put("C", "C");
        map.put("D", "D");
        map.put("E", "E");
        map.put("F", "F");
        map.put("G", "G");
        map.put("H", "H");
        map.put("I", "I");
        map.put("J", "J");
        map.put("K", "K");
        map.put("L", "L");
        map.put("M", "M");
        map.put("N", "N");
        map.put("O", "O");
        map.put("P", "P");
        map.put("Q", "Q");
        map.put("R", "R");
        map.put("S", "S");
        map.put("T", "T");
        map.put("U", "U");
        map.put("V", "V");
        map.put("W", "W");
        map.put("X", "X");
        map.put("Y", "Y");
        map.put("Z", "Z");

        map.put(":", ":");
        map.put("/", "/");
        map.put(File.separator, File.separator);
        map.put("1", "1");
        map.put("2", "2");
        map.put("3", "3");
        map.put("4", "4");
        map.put("5", "5");
        map.put("6", "6");
        map.put("7", "7");
        map.put("8", "8");
        map.put("9", "9");
        map.put("0", "0");
        map.put("_", "_");
        map.put("-", "-");
        map.put(".", ".");

        String temp = "";
        for (int i = 0; i < propPath.length(); i++) {
            if (map.get(propPath.charAt(i)+"")!=null) {
                temp += map.get(propPath.charAt(i)+"");
            }
        }
        propPath = temp;
        File file = new File(propPath);
        OutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            try {
                props.store(fos, "Update value");
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            logger.error("file update error");
        } finally {
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
    }

    public static void updateProperties1(String name,Properties props) {
        String propPath = Constant.DB_PATH() + name;

        HashMap<String, String> map = new HashMap<String, String>();
        map.put("a", "a");
        map.put("b", "b");
        map.put("c", "c");
        map.put("d", "d");
        map.put("e", "e");
        map.put("f", "f");
        map.put("g", "g");
        map.put("h", "h");
        map.put("i", "i");
        map.put("j", "j");
        map.put("k", "k");
        map.put("l", "l");
        map.put("m", "m");
        map.put("n", "n");
        map.put("o", "o");
        map.put("p", "p");
        map.put("q", "q");
        map.put("r", "r");
        map.put("s", "s");
        map.put("t", "t");
        map.put("u", "u");
        map.put("v", "v");
        map.put("w", "w");
        map.put("x", "x");
        map.put("y", "y");
        map.put("z", "z");

        map.put("A", "A");
        map.put("B", "B");
        map.put("C", "C");
        map.put("D", "D");
        map.put("E", "E");
        map.put("F", "F");
        map.put("G", "G");
        map.put("H", "H");
        map.put("I", "I");
        map.put("J", "J");
        map.put("K", "K");
        map.put("L", "L");
        map.put("M", "M");
        map.put("N", "N");
        map.put("O", "O");
        map.put("P", "P");
        map.put("Q", "Q");
        map.put("R", "R");
        map.put("S", "S");
        map.put("T", "T");
        map.put("U", "U");
        map.put("V", "V");
        map.put("W", "W");
        map.put("X", "X");
        map.put("Y", "Y");
        map.put("Z", "Z");

        map.put(":", ":");
        map.put("/", "/");
        map.put(File.separator, File.separator);
        map.put("1", "1");
        map.put("2", "2");
        map.put("3", "3");
        map.put("4", "4");
        map.put("5", "5");
        map.put("6", "6");
        map.put("7", "7");
        map.put("8", "8");
        map.put("9", "9");
        map.put("0", "0");
        map.put("_", "_");
        map.put("-", "-");
        map.put(".", ".");

        String temp = "";
        for (int i = 0; i < propPath.length(); i++) {
            if (map.get(propPath.charAt(i)+"")!=null) {
                temp += map.get(propPath.charAt(i)+"");
            }
        }
        propPath = temp;
        FileWriter fileWritter = null;
        BufferedWriter bufferWritter = null;
        try {
            fileWritter = new FileWriter(propPath,false);
            bufferWritter = new BufferedWriter(fileWritter);
            Set<Object> keySet = props.keySet();
            StringBuffer buffer = new StringBuffer();
            for(Object s : keySet){
                buffer.append(String.valueOf(s)).append("=").append(String.valueOf(props.get(s)));
                buffer.append("\r\n");
            }
            bufferWritter.write(buffer.toString());
            bufferWritter.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fileWritter != null){
                try{
                    fileWritter.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            if(bufferWritter != null){
                try{
                    bufferWritter.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    public static void safeClose(InputStream fis) {
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                logger.error(e.getMessage());
            }
        }
    }

}
